﻿//  --------------------------------
//  Copyright (c) 2010 Michael Schuler, Sascha Burger. All rights reserved.
//  This source code is made available under the terms of the Microsoft Public License (Ms-PL)
//  http://p2pmessaging.codeplex.com/license
//  ---------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Practices.Unity;
using NLog;
using p2pMessaging.BL;
using p2pMessaging.BL.Plugin;
using p2pMessaging.Interfaces;
using p2pMessaging.Interfaces.Contact;

namespace p2pMessaging.Contracts
{
	/// <summary>
	/// IoC service locator.
	/// </summary>
	public static class ServiceLocator
	{
		private static readonly IUnityContainer myContainer;
		
		/// <summary>
		/// Initializes static members of the <see cref="ServiceLocator"/> class.
		/// </summary>
		static ServiceLocator()
		{
			myContainer = new UnityContainer();
			myContainer.RegisterType<IContactService, ContactService>();
			myContainer.RegisterType<ICryptographyService, CryptographyService>();
			myContainer.RegisterType<IMessageService, EmailMessageService>("Email");
			myContainer.RegisterType<IMessageService, P2PMessageService>("P2P");
			myContainer.RegisterType<IPersistenceService, LoungeRepositoryPersistenceService>();
			myContainer.RegisterType<ISerializeService, SerializeService>();
		}

		/// <summary>
		/// Get an implementation of interface <see cref="T"/>.
		/// </summary>
		/// <typeparam name="T">Interface of the service.</typeparam>
		/// <returns>Implementation of <see cref="T"/>.</returns>
		/// <exception cref="Exception">If no implementation was found.</exception>
		public static T Get<T>()
		{
			try
			{
				Logger logger = LogManager.GetLogger(typeof(T).Name);
				logger.Debug("Create new instance of {0}.", typeof(T).Name);
				T impl = myContainer.Resolve<T>();
				return impl;
			}
			catch (Exception ex)
			{
				Debug.WriteLine(ex.Message);
				Debug.WriteLine(ex.StackTrace);
				throw;
			}
		}
		
		/// <summary>
		/// Get the IMessageService plugin by its Guid.
		/// </summary>
		/// <param name="pluginId">Guid of the plugin.</param>
		/// <returns>Implementation of <see cref="IMessageService"/> or null.</returns>
		public static IMessageService GetPlugin(Guid pluginId)
		{
			IEnumerable<IMessageService> services = myContainer.ResolveAll<IMessageService>();
			foreach (IMessageService service in services)
			{
				if (service.PluginId.Equals(pluginId))
				{
					return service;
				}
			}
			
			return null;
		}
		
		public static void Send(IMessage message)
		{
			MessageServiceStrategy messageServiceStrategy = new MessageServiceStrategy();
			LoggingMessageServiceDecorator decorator = new LoggingMessageServiceDecorator(messageServiceStrategy);
			decorator.Send(message);
		}

		/// <summary>
		/// Get an implementation of interface <see cref="T"/> by the name.
		/// </summary>
		/// <typeparam name="T">Interface of the service.</typeparam>
		/// <param name="name">Name of the implementation.</param>
		/// <returns>Implementation of <see cref="T"/>.</returns>
		/// <exception cref="Exception">If no implementation was found.</exception>
		public static T Get<T>(string name)
		{
			try
			{
				//Logger logger = LogManager.GetLogger(typeof(T).Name);
				//logger.Debug("Create new instance of {0}.", typeof(T).Name);

				T impl = myContainer.Resolve<T>(name);
				return impl;
			}
			catch (Exception ex)
			{
				Debug.WriteLine(ex.Message);
				Debug.WriteLine(ex.StackTrace);
				throw;
			}
		}
	}
}
